~function () {

  class Drag {
    constructor(el, options = {}) {
      if (!el || el.nodeType !== 1) {
        throw ReferenceError('el is a must pass parameter and must be an element object')
      }
      this.subDown = new Subscribe();
      this.subMove = new Subscribe();
      this.subUp = new Subscribe();
      let {
        selector = el
      } = options;
      // 需要移动的盒子
      this.el = this.getDom(el);
      // 鼠标悬浮的元素来移动 el 元素
      this.dragTarget = this.getDom(selector);

      this.startX = 0;
      this.startY = 0;
      this.startL = 0;
      this.startT = 0;

      // 屏幕高度宽度
      this.winW = document.documentElement.clientWidth;
      this.winH = document.documentElement.clientHeight;
      // 盒子的高度宽度
      this.boxW = this.el.offsetWidth;
      this.boxH = this.el.offsetHeight;

      // 鼠标移动后当前的盒子位置 
      this.curL = 0;
      this.curT = 0;

      this.MOVE = null;
      this.UP = null;
      this.dragTarget.addEventListener('mousedown', this.down.bind(this));
    }
    getDom(selector) {
      return typeof selector === 'string' ? document.querySelector(selector) : selector;
    }
    down(ev) {
      this.startX = ev.clientX;
      this.startY = ev.clientY;
      this.startL = this.el.offsetLeft;
      this.startT = this.el.offsetTop;
      this.MOVE = this.move.bind(this);
      this.UP = this.up.bind(this);

      document.addEventListener('mousemove', this.MOVE);
      document.addEventListener('mouseup', this.UP);
      // 通知执行函数
      this.subDown.fire(this, ev);
    }
    move(ev) {
      let {
        startX,
        startY,
        startL,
        startT
      } = this;
      this.curL = ev.clientX - startX + startL;
      this.curT = ev.clientY - startY + startT;

      // 边界判断
      let minL = 0;
      let minT = 0;
      let maxL = this.winW - this.boxW;
      let maxT = this.winH - this.boxH;
      this.curT = this.curT < minT ? minT : (this.curT > maxT ? maxT : this.curT);
      this.curL = this.curL < minL ? minL : (this.curL > maxL ? maxL : this.curL);
      this.el.style.top = this.curT + 'px';
      this.el.style.left = this.curL + 'px';
      // 通知执行函数
      this.subMove.fire(this, ev);
    }
    up(ev) {
      document.removeEventListener('mousemove', this.MOVE);
      document.removeEventListener('mouseup', this.UP);
      this.MOVE = null;
      this.UP = null;
      // 通知执行函数
      this.subUp.fire(this, ev);
    }
  }

  window.Drag = Drag;
}()
